package com.example.yijian.edit.timelineEditor;

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.example.yijian.R;
import com.example.yijian.edit.data.BackupData;
import com.example.yijian.utils.LogUtils;
import com.example.yijian.utils.datainfo.ClipInfo;
import com.meicam.sdk.NvsMultiThumbnailSequenceView;

import java.util.ArrayList;
import java.util.NavigableMap;

/**
 * Created by admin on 2018/6/8.
 */

public class NvsTimelineTimeSpanExt extends RelativeLayout {
    private String TAG = "NvsTimelineTimeSpanExt";
    private static final long preciseAdjustValue = 100000;//0.1秒
    private float prevRawX = 0;
    private OnTrimInChangeListener mOnTrimInChangeListener;
    private OnTrimOutChangeListener mOnTrimOutChangeListener;
    private OnMarginChangeListener mMarginChangeListener;
    //
    private long originInPoint = 0;
    private long originOutPoint = 0;
    private long mInPoint = 0;
    private long mOutPoint = 0;
    private double mPixelPerMicrosecond = 0D;
    private int mTotalWidth = 0;
    //
    private long minDraggedTimeSpanDuration = 1000000;
    private int minDraggedTimeSpanPixel = 0;
    private int originLeft = 0;
    private int originRight = 0;

    MultiThumbnailSequenceView multiThumbnailSequenceView;

    private int mLTopHandleHeight = 0;
    private int mLLeftHandleWidth = 0;

    private View timeSpanshadowView;
    private RelativeLayout mLTopHandle;
    private RelativeLayout mLBottomLayout;
    private RelativeLayout mLLeftLayout;
    private RelativeLayout mLRightLayout;
    private ImageView mLLeftHandle;
    private ImageView mLRightHandle;
    private ImageView mLeftHandleImage;
    private RelativeLayout mRTopHandle;
    private RelativeLayout mRBottomLayout;
    private RelativeLayout mRLeftLayout;
    private RelativeLayout mRRightLayout;
    private ImageView mRLeftHandle;
    private ImageView mRRightHandle;
    private ImageView mRightHandleImage;
    private TextView tvDuration;
    private TextView tvCurve;
    private int mCurClipIndex;
    ArrayList<ClipInfo> mClipArrayList;

    public NvsTimelineTimeSpanExt(Context context) {
        super(context);
        mClipArrayList = BackupData.instance().cloneClipInfoData();
        mCurClipIndex = BackupData.instance().getClipIndex();
        init(context);
        initListener();
    }

    private void init(Context context) {
        View parentRoot = LayoutInflater.from(context).inflate(R.layout.timespanext, this);
        timeSpanshadowView = parentRoot.findViewById(R.id.timeSpanShadow);
        mLTopHandle = (RelativeLayout) parentRoot.findViewById(R.id.lTopHandle);
        mLTopHandleHeight = mLTopHandle.getLayoutParams().height;
        mLBottomLayout = (RelativeLayout) parentRoot.findViewById(R.id.lBottomLayout);
        mLLeftLayout = (RelativeLayout) parentRoot.findViewById(R.id.lLeftHandleLayout);
        mLRightLayout = (RelativeLayout) parentRoot.findViewById(R.id.lRightHandleLayout);
        mLLeftHandle = (ImageView) parentRoot.findViewById(R.id.lLeftHandle);
        mLRightHandle = (ImageView) parentRoot.findViewById(R.id.lRightHandle);
        mLeftHandleImage = (ImageView) parentRoot.findViewById(R.id.leftHandleImage);
        mLLeftHandleWidth = mLLeftHandle.getLayoutParams().width;
        mRTopHandle = (RelativeLayout) parentRoot.findViewById(R.id.rTopHandle);
        mRBottomLayout = (RelativeLayout) parentRoot.findViewById(R.id.rBottomLayout);
        mRLeftLayout = (RelativeLayout) parentRoot.findViewById(R.id.rLeftHandleLayout);
        mRRightLayout = (RelativeLayout) parentRoot.findViewById(R.id.rRightHandleLayout);
        mRLeftHandle = (ImageView) parentRoot.findViewById(R.id.rLeftHandle);
        mRRightHandle = (ImageView) parentRoot.findViewById(R.id.rRightHandle);
        mRightHandleImage = (ImageView) parentRoot.findViewById(R.id.rightHandleImage);
        tvDuration = parentRoot.findViewById(R.id.tv_duration);
        tvCurve = parentRoot.findViewById(R.id.tv_curve);
    }

    private void initListener() {
        mLTopHandle.setOnTouchListener(new OnTouchListener() {
            @SuppressLint("ClickableViewAccessibility")
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                minDraggedTimeSpanPixel = (int) Math.floor(minDraggedTimeSpanDuration * mPixelPerMicrosecond + 0.5D);
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        getParent().requestDisallowInterceptTouchEvent(true);
//                        mLBottomLayout.setVisibility(View.VISIBLE);
//                        mRBottomLayout.setVisibility(View.INVISIBLE);
//                        mLeftHandleImage.setImageResource(R.mipmap.trimline_select_left);
//                        mRightHandleImage.setImageResource(R.mipmap.trimline_default_right);

                        originLeft = getLeft();
                        originRight = getRight();
                        prevRawX = (int) event.getRawX();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        getParent().requestDisallowInterceptTouchEvent(true);
                        float tempRawX = event.getRawX();
                        int dx = (int) Math.floor(tempRawX - prevRawX + 0.5D);
                        LogUtils.e("mLTopHandle", "onTouch--dx->" + dx);
                        LogUtils.e("mLTopHandle", "onTouch--mInPoint->" + mInPoint);
                        LogUtils.e("mLTopHandle", "onTouch--originInPoint->" + originInPoint);
                        if (dx < 0 && mInPoint <= originInPoint) {
                            break;
                        }
                        prevRawX = tempRawX;
                        leftHandleMove(dx);
                        setTrimInCallback(false);
                        break;
                    case MotionEvent.ACTION_UP:
                        getParent().requestDisallowInterceptTouchEvent(false);
                        setTrimInCallback(true);
                        break;
                }
                return true;
            }
        });
        mRTopHandle.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                minDraggedTimeSpanPixel = (int) Math.floor(minDraggedTimeSpanDuration * mPixelPerMicrosecond + 0.5D);
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        getParent().requestDisallowInterceptTouchEvent(true);
//                        mLBottomLayout.setVisibility(View.INVISIBLE);
//                        mRBottomLayout.setVisibility(View.VISIBLE);
//                        mLeftHandleImage.setImageResource(R.mipmap.trimline_default_left);
//                        mRightHandleImage.setImageResource(R.mipmap.trimline_select_right);

                        originLeft = getLeft();
                        originRight = getRight();
                        prevRawX = (int) event.getRawX();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        getParent().requestDisallowInterceptTouchEvent(true);
                        float tempRawX = (int) event.getRawX();
                        int dx = (int) Math.floor(tempRawX - prevRawX + 0.5D);
                        LogUtils.e("mLTopHandle", "onTouch--dx->" + dx);
                        LogUtils.e("mLTopHandle", "onTouch--mInPoint->" + mOutPoint);
                        LogUtils.e("mLTopHandle", "onTouch--originInPoint->" + originOutPoint);
                        if (dx > 0 && mOutPoint >= originOutPoint) {
                            break;
                        }
                        prevRawX = tempRawX;
                        rightHandleMove(dx);
                        setTrimOutCallback(false);
                        break;
                    case MotionEvent.ACTION_UP:
                        getParent().requestDisallowInterceptTouchEvent(false);
                        setTrimOutCallback(true);
                        break;
                }
                return true;
            }
        });
        mLLeftLayout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int tmpDx = getAdjustSpanValue();
                tmpDx = -tmpDx;
                leftHandleMove(tmpDx);
                setTrimInCallback(true);
            }
        });
        mLLeftHandle.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mLLeftLayout.callOnClick();
            }
        });

        mLRightLayout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int tmpDx = getAdjustSpanValue();
                leftHandleMove(tmpDx);
                setTrimInCallback(true);
            }
        });

        mLRightHandle.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mLRightLayout.callOnClick();
            }
        });
        mRLeftLayout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int tmpDx = getAdjustSpanValue();
                tmpDx = -tmpDx;
                rightHandleMove(tmpDx);
                setTrimOutCallback(true);
            }
        });
        mRLeftHandle.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mRLeftLayout.callOnClick();
            }
        });
        mRRightLayout.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                int tmpDx = getAdjustSpanValue();
                rightHandleMove(tmpDx);
                setTrimOutCallback(true);
            }
        });
        mRRightHandle.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mRRightLayout.callOnClick();
            }
        });
    }

    public void setMultiThumbnailSequenceView(MultiThumbnailSequenceView thumbnailSequenceView) {
        this.multiThumbnailSequenceView = thumbnailSequenceView;
    }

    public View getTimeSpanshadowView() {
        return timeSpanshadowView;
    }

    public long getInPoint() {
        return mInPoint;
    }

    public int getIndex() {
        return mCurClipIndex;
    }

    public void setIndex(int index) {
        this.mCurClipIndex = index;
    }

    public void setInPoint(long mInPoint) {
        this.mInPoint = mInPoint;
        this.originInPoint = mInPoint;
    }


    public long getOutPoint() {
        return mOutPoint;
    }

    public void setOutPoint(long mOutPoint) {
        this.mOutPoint = mOutPoint;
        this.originOutPoint = mOutPoint;
    }

    public void setDuration(String duration) {
        tvDuration.setText(duration);
    }

    public void setCurveName(String mName) {
        tvCurve.setText(mName);
    }

    //formate time
    public String formatTimeStrWithUs(long us) {
        double second = us / 1000000.0;
        return String.format("%.1fs", second);
    }


    public void setPixelPerMicrosecond(double mPixelPerMicrosecond) {
        this.mPixelPerMicrosecond = mPixelPerMicrosecond;
    }

    public int getLTopHandleHeight() {
        return mLTopHandleHeight;
    }

    public int getLLeftHandleWidth() {
        return mLLeftHandleWidth;
    }

    public void setTotalWidth(int totalWidth) {
        this.mTotalWidth = totalWidth;
    }


    private int getAdjustSpanValue() {
        return (int) Math.floor(preciseAdjustValue * mPixelPerMicrosecond + 0.5D);
    }

    public void setOnChangeListener(OnTrimInChangeListener onChangeListener) {
        this.mOnTrimInChangeListener = onChangeListener;
    }

    public void setOnChangeListener(OnTrimOutChangeListener onChangeListener) {
        this.mOnTrimOutChangeListener = onChangeListener;
    }

    public void setMarginChangeListener(OnMarginChangeListener marginChangeListener) {
        this.mMarginChangeListener = marginChangeListener;
    }


    public interface OnTrimInChangeListener {
        void onChange(long timeStamp, boolean isDragEnd);
    }

    public interface OnTrimOutChangeListener {
        void onChange(long timeStamp, boolean isDragEnd);
    }

    public interface OnMarginChangeListener {
        void onChange(int leftMargin, int timeSpanWidth);
    }

    /**
     * 触摸点为右边缘
     * Touch point is right edge
     */
    private void right(int dx) {
        originRight += dx;
        if (originRight >= mTotalWidth) {
            originRight = mTotalWidth;
        }
//        if (originRight - mLLeftHandleWidth - (originLeft + mLLeftHandleWidth) < (minDraggedTimeSpanPixel+mLLeftHandleWidth)) {
//            originRight = originLeft + minDraggedTimeSpanPixel + 3 * mLLeftHandleWidth;
//        }
        if (originRight < originLeft + 4 * mLLeftHandleWidth + (minDraggedTimeSpanPixel > mLLeftHandleWidth * 2 ? minDraggedTimeSpanPixel : 0)) {
            originRight = originLeft + 4 * mLLeftHandleWidth + (minDraggedTimeSpanPixel > mLLeftHandleWidth * 2 ? minDraggedTimeSpanPixel : 0);
        }
    }

    /**
     * 触摸点为左边缘
     * Touch point is the left edge
     */
    private void left(int dx) {
        originLeft += dx;
        if (originLeft < 0) {
            originLeft = 0;
        }
//        if (originRight - mLLeftHandleWidth - (originLeft + mLLeftHandleWidth) < (minDraggedTimeSpanPixel + mLLeftHandleWidth)) {
//            originLeft = originRight - 2 * mLLeftHandleWidth - minDraggedTimeSpanPixel - mLLeftHandleWidth;
//        }
        if (originLeft > originRight - 4 * mLLeftHandleWidth - (minDraggedTimeSpanPixel > 50 ? minDraggedTimeSpanPixel : 0)) {
            originLeft = originRight - 4 * mLLeftHandleWidth - (minDraggedTimeSpanPixel > 50 ? minDraggedTimeSpanPixel : 0);
        }
    }

    private void leftHandleMove(int dx) {
        left(dx);
        LayoutParams lp = (LayoutParams) getLayoutParams();
        lp.width = originRight - originLeft;
        lp.setMargins(originLeft, LayoutParams.MATCH_PARENT, mTotalWidth - originRight, 0);
        setLayoutParams(lp);
        int leftPixel = originLeft;
//        int leftPixel = originLeft + mLLeftHandleWidth;
        int rightPixel = originRight - mLLeftHandleWidth;
        mInPoint = multiThumbnailSequenceView.mapTimelineExtPosFromX(leftPixel);
        setDuration(formatTimeStrWithUs(mOutPoint - mInPoint));
        if (mMarginChangeListener != null) {
            mMarginChangeListener.onChange(leftPixel, rightPixel - leftPixel);
        }
    }

    private void rightHandleMove(int dx) {
        right(dx);
        LayoutParams lp = (LayoutParams) getLayoutParams();
        lp.width = originRight - originLeft;
        lp.setMargins(originLeft, LayoutParams.MATCH_PARENT, mTotalWidth - originRight, 0);
        setLayoutParams(lp);
        int leftPixel = originLeft + mLLeftHandleWidth;
        int rightPixel = originRight - mLLeftHandleWidth;
        mOutPoint = multiThumbnailSequenceView.mapTimelineExtPosFromX(rightPixel);
        setDuration(formatTimeStrWithUs(mOutPoint - mInPoint));
        if (mMarginChangeListener != null) {
            mMarginChangeListener.onChange(leftPixel, rightPixel - leftPixel);
        }
    }

    private void setTrimInCallback(boolean isDragEnd) {
        if (mOnTrimInChangeListener != null) {
            float speed = mClipArrayList.get(mCurClipIndex).getSpeed();
            speed = speed <= 0 ? 1.0f : speed;
            long newTrimIn = (long) (mInPoint * speed);
            LogUtils.e(TAG, "setTrimInCallback--->" + newTrimIn);
            mClipArrayList.get(mCurClipIndex).changeTrimIn(newTrimIn);
            BackupData.instance().setClipInfoData(mClipArrayList);
            mOnTrimInChangeListener.onChange(mInPoint, isDragEnd);
        }
    }

    private void setTrimOutCallback(boolean isDragEnd) {
        if (mOnTrimOutChangeListener != null) {
            float speed = mClipArrayList.get(mCurClipIndex).getSpeed();
            speed = speed <= 0 ? 1.0f : speed;
            long newTrimOut = (long) (mOutPoint * speed);
            LogUtils.e(TAG, "setTrimInCallback--->" + newTrimOut);
            mClipArrayList.get(mCurClipIndex).changeTrimOut(newTrimOut);
            BackupData.instance().setClipInfoData(mClipArrayList);
            mOnTrimOutChangeListener.onChange(mOutPoint, isDragEnd);
        }
    }
}
